/*
 * Copyright (c) 2021 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#ifndef HIVIEWDFX_HITRACE_H
#define HIVIEWDFX_HITRACE_H
/**
 * @addtogroup Hitrace
 * @{
 *
 * @brief hiTraceMeter为开发者提供系统性能打点接口。
 *
 * 开发者通过在自己的业务逻辑中的关键代码位置调用HiTraceMeter系统跟踪提供的API接口，能够有效进行关键执行流程耗时度量和问题定位。
 *
 * @brief hitraceChain为开发者提供跨线程、跨进程的分布式跟踪能力。
 * HiTraceChain支持在业务执行流程中，生成和传递唯一跟踪标识，在业务流程中输出的各类调试信息中（包括应用事件、系统事件、日志等）携带该跟踪标识。
 * 在调试、问题定位过程中，开发人员可以通过该唯一跟踪标识将本次业务流程端到端的各类信息快速关联起来。
 *
 * @syscap SystemCapability.HiviewDFX.HiTrace
 *
 * @since 10
 */

/**
 * @file trace.h
 * @library libhitrace_ndk.z.so
 *
 * @brief HiTraceMeterH模块打点接口定义，通过这些接口实现性能打点相关功能。
 *
 * 使用示例:\n
 * 同步时间片跟踪事件：\n
 *     OH_HiTrace_StartTrace("hitraceTest");\n
 * 	   OH_HiTrace_FinishTrace();\n
 * 结果输出：\n
 *     <...>-1668    (-------) [003] ....   135.059377: tracing_mark_write: B|1668|H:hitraceTest\n
 *     <...>-1668    (-------) [003] ....   135.059415: tracing_mark_write: E|1668|\n
 * 异步时间片跟踪事件：\n
 * 	   OH_HiTrace_StartAsyncTrace("hitraceTest", 123);\n
 *     OH_HiTrace_FinishAsyncTrace("hitraceTest", 123);\n
 * 结果输出：\n
 *     <...>-2477    (-------) [001] ....   396.427165: tracing_mark_write: S|2477|H:hitraceTest 123\n
 *     <...>-2477    (-------) [001] ....   396.427196: tracing_mark_write: F|2477|H:hitraceTest 123\n
 * 整数值跟踪事件：\n
 *     OH_HiTrace_CountTrace("hitraceTest", 500);\n
 * 结果输出：\n
 *     <...>-2638    (-------) [002] ....   458.904382: tracing_mark_write: C|2638|H:hitraceTest 500\n
 *
 * @since 10
 */
#include <stdint.h>

#ifdef __cplusplus
extern "C" {
#endif

/**
 * @brief HiTraceId是否有效标志
 *
 * @syscap SystemCapability.HiviewDFX.HiTrace
 *
 * @since 12
 */
typedef enum HiTraceId_Valid {
    /**
     * @brief 无效HiTraceId
     *
     * @syscap SystemCapability.HiviewDFX.HiTrace
     *
     * @since 12
     */
    HITRACE_ID_INVALID = 0,

    /**
     * @brief 有效HiTraceId
     *
     * @syscap SystemCapability.HiviewDFX.HiTrace
     *
     * @since 12
     */
    HITRACE_ID_VALID = 1,
} HiTraceId_Valid;

/**
 * @brief HiTrace版本号
 *
 * @syscap SystemCapability.HiviewDFX.HiTrace
 *
 * @since 12
 */
typedef enum HiTrace_Version {
    /**
     * @brief 版本1
     *
     * @syscap SystemCapability.HiviewDFX.HiTrace
     *
     * @since 12
     */
    HITRACE_VER_1 = 0,
} HiTrace_Version;

/**
 * @brief HiTrace标志位
 *
 * @syscap SystemCapability.HiviewDFX.HiTrace
 *
 * @since 12
 */
typedef enum HiTrace_Flag {
    /**
     * @brief 默认值
     *
     * @syscap SystemCapability.HiviewDFX.HiTrace
     *
     * @since 12
     */
    HITRACE_FLAG_DEFAULT = 0,

    /**
     * @brief 跟踪同步和异步调用。默认：仅跟踪同步调用。
     *
     * @syscap SystemCapability.HiviewDFX.HiTrace
     *
     * @since 12
     */
    HITRACE_FLAG_INCLUDE_ASYNC = 1 << 0,

    /**
     * @brief 不创建child span。默认创建。
     *
     * @syscap SystemCapability.HiviewDFX.HiTrace
     *
     * @since 12
     */
    HITRACE_FLAG_DONOT_CREATE_SPAN = 1 << 1,

    /**
     * @brief 在span中输出跟踪点信息，默认不输出跟踪点信息。
     *
     * @syscap SystemCapability.HiviewDFX.HiTrace
     *
     * @since 12
     */
    HITRACE_FLAG_TP_INFO = 1 << 2,

    /**
     * @brief 不输出开始和结束信息，默认输出开始和结束信息。
     *
     * @syscap SystemCapability.HiviewDFX.HiTrace
     *
     * @since 12
     */
    HITRACE_FLAG_NO_BE_INFO = 1 << 3,

    /**
     * @brief 不添加id到日志中，默认添加id到日志中。
     *
     * @syscap SystemCapability.HiviewDFX.HiTrace
     *
     * @since 12
     */
    HITRACE_FLAG_DONOT_ENABLE_LOG = 1 << 4,

    /**
     * @brief 跟踪是由故障触发的。
     *
     * @syscap SystemCapability.HiviewDFX.HiTrace
     *
     * @since 12
     */
    HITRACE_FLAG_FAULT_TRIGGER = 1 << 5,

    /**
     * @brief 仅输出span中的设备到设备跟踪点信息。默认值：不输出设备到设备跟踪点信息。
     *
     * @syscap SystemCapability.HiviewDFX.HiTrace
     *
     * @since 12
     */
    HITRACE_FLAG_D2D_TP_INFO = 1 << 6,
} HiTrace_Flag;

/**
 * @brief HiTrace打点类型
 *
 * @syscap SystemCapability.HiviewDFX.HiTrace
 *
 * @since 12
 */
typedef enum HiTrace_Tracepoint_Type {
    /**
     * @brief 客户端发送
     *
     * @syscap SystemCapability.HiviewDFX.HiTrace
     *
     * @since 12
     */
    HITRACE_TP_CS = 0,
    /**
     * @brief 客户端接收
     *
     * @syscap SystemCapability.HiviewDFX.HiTrace
     *
     * @since 12
     */
    HITRACE_TP_CR = 1,
    /**
     * @brief 服务端发送
     *
     * @syscap SystemCapability.HiviewDFX.HiTrace
     *
     * @since 12
     */
    HITRACE_TP_SS = 2,
    /**
     * @brief 服务端接收
     *
     * @syscap SystemCapability.HiviewDFX.HiTrace
     *
     * @since 12
     */
    HITRACE_TP_SR = 3,
    /**
     * @brief 整体信息
     *
     * @syscap SystemCapability.HiviewDFX.HiTrace
     *
     * @since 12
     */
    HITRACE_TP_GENERAL = 4,
} HiTrace_Tracepoint_Type;

/**
 * @brief HiTrace通信模式枚举
 *
 * @syscap SystemCapability.HiviewDFX.HiTrace
 *
 * @since 12
 */
typedef enum HiTrace_Communication_Mode {
    /**
     * @brief 未指明
     *
     * @syscap SystemCapability.HiviewDFX.HiTrace
     *
     * @since 12
     */
    HITRACE_CM_DEFAULT = 0,
    /**
     * @brief 线程间通信
     *
     * @syscap SystemCapability.HiviewDFX.HiTrace
     *
     * @since 12
     */
    HITRACE_CM_THREAD = 1,
    /**
     * @brief 进程间通信
     *
     * @syscap SystemCapability.HiviewDFX.HiTrace
     *
     * @since 12
     */
    HITRACE_CM_PROCESS = 2,
    /**
     * @brief 设备间通信
     *
     * @syscap SystemCapability.HiviewDFX.HiTrace
     *
     * @since 12
     */
    HITRACE_CM_DEVICE = 3,
} HiTrace_Communication_Mode;

/**
 * @brief HiTraceId定义
 *
 * @struct HiTraceId
 *
 * @syscap SystemCapability.HiviewDFX.HiTrace
 *
 * @since 12
 */
typedef struct HiTraceId {
#if __BYTE_ORDER == __LITTLE_ENDIAN
    /** HiTraceId是否有效 */
    uint64_t valid : 1;
    /** HiTraceId的版本号 */
    uint64_t ver : 3;
    /** HiTraceId的链Id */
    uint64_t chainId : 60;
    /** HiTraceId的标志位 */
    uint64_t flags : 12;
    /** HiTraceId的当前跨度号 */
    uint64_t spanId : 26;
    /** HiTraceId的父跨度号 */
    uint64_t parentSpanId : 26;
#elif __BYTE_ORDER == __BIG_ENDIAN
    /** HiTraceId的链Id */
    uint64_t chainId : 60;
    /** HiTraceId的版本号 */
    uint64_t ver : 3;
    /** HiTraceId是否有效 */
    uint64_t valid : 1;
    /** HiTraceId的父跨度号 */
    uint64_t parentSpanId : 26;
    /** HiTraceId的当前跨度号 */
    uint64_t spanId : 26;
    /** HiTraceId的标志位 */
    uint64_t flags : 12;
#else
#error "ERROR: No BIG_LITTLE_ENDIAN defines."
#endif
} HiTraceId;

/**
 * @brief 开始跟踪进程实现。
 *
 * 启动跟踪；生成HiTraceId结构体并设置到当前线程TLS中。第一次调用有效，否则无效。
 *
 * @param name 跟踪业务名.
 * @param flags 跟踪功能标志，见{@link HiTrace_Flag}。
 * @return 生成的HitraceId，见{@link HiTraceId}。
 *
 * @syscap SystemCapability.HiviewDFX.HiTrace
 *
 * @since 12
 */
HiTraceId OH_HiTrace_BeginChain(const char *name, int flags);

/**
 * @brief 如果给定的跟踪ID有效，则停止进程跟踪并清除当前线程的跟踪ID，否则不执行任何操作。
 *
 * 停止跟踪；清除当前线程TLS中HiTraceId内容。
 *
 * @syscap SystemCapability.HiviewDFX.HiTrace
 *
 * @since 12
 */
void OH_HiTrace_EndChain();

/**
 * @brief 获取当前线程的跟踪ID，如果没有属于当前线程的跟踪ID，则返回一个无效的跟踪ID。
 *
 * 从当前线程TLS中获取跟踪标识。
 *
 * @return 当前线程的{@link HiTraceId}。如果调用线程没有HiTraceId，则返回无效的HiTraceId。
 *
 * @syscap SystemCapability.HiviewDFX.HiTrace
 *
 * @since 12
 */
HiTraceId OH_HiTrace_GetId();

/**
 * @brief 将id设置为当前线程的跟踪id。如果ID无效，则不执行任何操作。
 *
 * 设置HiTraceId结构体内容到当前线程TLS中。
 *
 * @param id 将id设置为当前线程的跟踪id，见{@link HiTraceId}。
 *
 * @syscap SystemCapability.HiviewDFX.HiTrace
 *
 * @since 12
 */
void OH_HiTrace_SetId(const HiTraceId *id);

/**
 * @brief 清除当前线程的跟踪ID并将其设置为无效。
 *
 * 清除当前线程TLS中的HiTraceId结构体。
 *
 * @syscap SystemCapability.HiviewDFX.HiTrace
 *
 * @since 12
 */
void OH_HiTrace_ClearId(void);

/**
 * @brief 根据当前线程的跟踪id创建一个新的span id。
 *
 * 根据当前线程TLS中的HiTraceId结构体，生成新的子分支以及对应的新HiTraceI结构体。
 *
 * @return 有效的跨度跟踪ID，见{@link HiTraceId}。否则，如果不允许创建跨度，则跟踪当前线程的ID。
 *
 * @syscap SystemCapability.HiviewDFX.HiTrace
 *
 * @since 12
 */
HiTraceId OH_HiTrace_CreateSpan(void);

/**
 * @brief 打印hitrace信息，包括跟踪ID信息。
 *
 * 输出埋点信息，包括通信方式、埋点类型、时间戳、分支等信息。
 *
 * @param mode 跟踪通信模式，见{@link HiTrace_Communication_Mode}。
 * @param type 跟踪信息类型，见{@link HiTrace_Tracepoint_Type}。
 * @param id 需要打印的跟踪ID，见{@link HiTraceId}。
 * @param fmt 需要打印的自定义信息。
 *
 * @syscap SystemCapability.HiviewDFX.HiTrace
 *
 * @since 12
 */
void OH_HiTrace_Tracepoint(
    HiTrace_Communication_Mode mode, HiTrace_Tracepoint_Type type, const HiTraceId *id, const char *fmt, ...);

/**
 * @brief 初始化HiTraceId结构体。
 *
 * @param id 需要初始化的{@link HiTraceId}。
 *
 * @syscap SystemCapability.HiviewDFX.HiTrace
 *
 * @since 12
 */
void OH_HiTrace_InitId(HiTraceId *id);

/**
 * @brief 根据字节数组创建跟踪HiTraceId结构体。
 *
 * @param id 需要创建的{@link HiTraceId}。
 * @param pIdArray 字节数组。
 * @param len 字节数组长度。
 *
 * @syscap SystemCapability.HiviewDFX.HiTrace
 *
 * @since 12
 */
void OH_HiTrace_IdFromBytes(HiTraceId *id, const uint8_t *pIdArray, int len);

/**
 * @brief 判断trace id是否有效。
 *
 * HiTraceId结构体是否有效。
 *
 * @param id 需要判断的Trace id，见{@link HiTraceId}。
 * @return 如果跟踪ID有效，则为True；否则为false。
 *
 * @syscap SystemCapability.HiviewDFX.HiTrace
 *
 * @since 12
 */
bool OH_HiTrace_IsIdValid(const HiTraceId *id);

/**
 * @brief 判断跟踪id是否启用了跟踪标志。
 *
 * HiTraceId结构体的某标志是否置位。
 *
 * @param id 需要判断的Trace id，见{@link HiTraceId}。
 * @param flag 需要判断的flag，见{@link HiTrace_Flag}。
 * @return 如果跟踪ID已启用标志，则为true。
 *
 * @syscap SystemCapability.HiviewDFX.HiTrace
 *
 * @since 12
 */
bool OH_HiTrace_IsFlagEnabled(const HiTraceId *id, HiTrace_Flag flag);

/**
 * @brief 启用跟踪ID的指定跟踪标志。
 *
 * 设置某跟踪标志位到HiTraceId结构体中。
 *
 * @param id 需要启用标志的跟踪ID，见{@link HiTraceId}。
 * @param flag 跟踪ID中需要启用的指定跟踪标志，见{@link HiTrace_Flag}。
 *
 * @syscap SystemCapability.HiviewDFX.HiTrace
 *
 * @since 12
 */
void OH_HiTrace_EnableFlag(const HiTraceId *id, HiTrace_Flag flag);

/**
 * @brief 获取HiTraceId结构体中设置的标志位。
 *
 * @param id 需要获取标志位的HiTraceId结构体，见{@link HiTraceId}。
 *
 * @return HiTraceId结构体中设置的标志位。
 *
 * @syscap SystemCapability.HiviewDFX.HiTrace
 *
 * @since 12
 */
int OH_HiTrace_GetFlags(const HiTraceId *id);

/**
 * @brief 设置跟踪标志位到HiTraceId结构体中。
 *
 * @param id 需要设置跟踪标志位的HiTraceId结构体，见{@link HiTraceId}。
 * @param flags 跟踪ID中需要设置的指定跟踪标志，见{@link HiTrace_Flag}。
 *
 * @syscap SystemCapability.HiviewDFX.HiTrace
 *
 * @since 12
 */
void OH_HiTrace_SetFlags(HiTraceId *id, int flags);

/**
 * @brief 获取跟踪链ID。
 *
 * @param id 需要获取跟踪链ID的HiTraceId结构体，见{@link HiTraceId}。
 *
 * @return HiTraceId结构体中设置的跟踪链ID。
 *
 * @syscap SystemCapability.HiviewDFX.HiTrace
 *
 * @since 12
 */
uint64_t OH_HiTrace_GetChainId(const HiTraceId *id);

/**
 * @brief 设置跟踪链ID到HiTraceId结构体中。
 *
 * @param id 需要设置跟踪链ID的HiTraceId结构体，见{@link HiTraceId}。
 * @param chainId 需要设置的跟踪链ID。
 *
 * @syscap SystemCapability.HiviewDFX.HiTrace
 *
 * @since 12
 */
void OH_HiTrace_SetChainId(HiTraceId *id, uint64_t chainId);

/**
 * @brief 获取当前HiTraceId结构体中的分支ID。
 *
 * @param id 需要获取分支ID的HiTraceId结构体，见{@link HiTraceId}。
 *
 * @return HiTraceId结构体中设置的分支ID。
 *
 * @syscap SystemCapability.HiviewDFX.HiTrace
 *
 * @since 12
 */
uint64_t OH_HiTrace_GetSpanId(const HiTraceId *id);

/**
 * @brief 设置分支ID到HiTraceId结构体中。
 *
 * @param id 需要设置分支ID的HiTraceId结构体。
 * @param spanId 需要设置的分支ID。
 *
 * @syscap SystemCapability.HiviewDFX.HiTrace
 *
 * @since 12
 */
void OH_HiTrace_SetSpanId(HiTraceId *id, uint64_t spanId);

/**
 * @brief 获取当前HiTraceId结构体中的父分支ID。
 *
 * @param id 需要获取父分支ID的HiTraceId结构体中，见{@link HiTraceId}。
 *
 * @return HiTraceId结构体中设置的父分支ID。
 *
 * @syscap SystemCapability.HiviewDFX.HiTrace
 *
 * @since 12
 */
uint64_t OH_HiTrace_GetParentSpanId(const HiTraceId *id);

/**
 * @brief 设置HiTraceId结构的parentSpanId字符。
 *
 * @param id 需要设置父分支ID的HiTraceId结构体中，见{@link HiTraceId}。
 * @param parentSpanId 需要设置的父分支ID。
 *
 * @syscap SystemCapability.HiviewDFX.HiTrace
 *
 * @since 12
 */
void OH_HiTrace_SetParentSpanId(HiTraceId *id, uint64_t parentSpanId);

/**
 * @brief 将HiTraceId结构体转换为字节数组，用于缓存或者通信传递。
 *
 * @param id 需要转换的HiTraceId，见{@link HiTraceId}。
 * @param pIdArray 字节数组。
 * @param len 字节数组长度。
 *
 * @return 转换后的字节数组长度。
 *
 * @syscap SystemCapability.HiviewDFX.HiTrace
 *
 * @since 12
 */
int OH_HiTrace_IdToBytes(const HiTraceId* id, uint8_t* pIdArray, int len);

/**
 * @brief 标记一个同步跟踪耗时任务的开始。
 *
 * 同步跟踪打点接口OH_HiTrace_StartTrace和OH_HiTrace_FinishTrace必须配对使用。
 * OH_HiTrace_StartTrace和OH_HiTrace_FinishTrace函数对可以以嵌套模式使用，跟踪数据解析时使用栈式数据结构进行匹配。
 *
 * @param name 跟踪的名字。
 *
 * @since 10
 */
void OH_HiTrace_StartTrace(const char *name);

/**
 * @brief 标记一个同步跟踪耗时任务的结束。
 *
 * 必须和OH_HiTrace_StartTrace配对使用。跟踪数据解析时，和其前执行流程中最近的OH_HiTrace_StartTrace进行匹配。
 *
 * @since 10
 */
void OH_HiTrace_FinishTrace(void);

/**
 * @brief 标记一个异步跟踪耗时任务的开始。
 *
 * 用于在异步操作前调用进行开始打点，异步跟踪开始和结束数据由于不是顺序发生的，所以解析时需要通过一个唯一的taskId进行识别，这个taskId作为异步接口的参数传入。
 * 和OH_HiTrace_FinishAsyncTrace配对使用，参数name和taskId相同的这两个接口调用匹配成一个异步跟踪耗时任务。
 * 如果有多个相同name的任务需要跟踪或者对同一个任务跟踪多次，并且任务同时被执行，则每次调用startTrace的taskId不相同。
 * 如果具有相同name的任务是串行执行的，则taskId可以相同。
 *
 * @param name 异步跟踪的名字。
 * @param taskId 异步跟踪的ID。 异步跟踪开始和结束由于不是顺序发生的，所以需要通过name和每次执行唯一的taskId进行开始和结束的匹配。
 *
 * @since 10
 */
void OH_HiTrace_StartAsyncTrace(const char *name, int32_t taskId);

/**
 * @brief 标记一个异步跟踪耗时任务的结束。
 *
 * 在异步操作完成后如回调函数中调用，进行结束打点。
 * 和OH_HiTrace_StartAsyncTrace配对使用，参数name和taskId必须与异步跟踪的开始打点接口OH_HiTrace_StartAsyncTrace的对应参数值一致。
 *
 * @param name 异步跟踪的名字。
 * @param taskId 异步跟踪的ID。异步跟踪开始和结束由于不是顺序发生的，所以需要通过name和每次执行唯一的taskId进行开始和结束的匹配。
 *
 * @since 10
 */
void OH_HiTrace_FinishAsyncTrace(const char *name, int32_t taskId);

/**
 * @brief 用于跟踪给定整数变量名和整数值。
 *
 * 多次执行该接口可以跟踪给定整数变量在不同时刻的数值变化。
 *
 * @param name 整数变量跟踪的名字，不必与真实变量名相同。
 * @param count 整数数值，一般可以传入整数变量。
 *
 * @since 10
 */
void OH_HiTrace_CountTrace(const char *name, int64_t count);

#ifdef __cplusplus
}
#endif
#endif // HIVIEWDFX_HITRACE_H